function Observer()
{
	this.chain;
	this.Update = function()
   {
      return;
   }
}

function Subject()
{
   this.observerHash = [];
}

Subject.prototype.Notify = function( context, chain )
{
	if( this.observerHash[chain] == null || this.observerHash[chain] == undefined ){
		//property is not bound
	      return;
	}
	var m_count = this.observerHash[chain].Count();
   
   for( var i = 0; i < m_count; i++ ){
	   this.observerHash[chain].GetAt(i).Update( context );
   }
}

Subject.prototype.AddObserver = function( observer )
{
	if( !observer.Update || !observer.chain ){
      throw 'Wrong parameter';
   }
   if( this.observerHash[observer.chain] == null || this.observerHash[observer.chain] == undefined ){
	   this.observerHash[observer.chain] = new ArrayList();
   }
   this.observerHash[observer.chain].Add( observer );
}

Subject.prototype.RemoveObserver = function( observer )
{
   if( !observer.Update || !observer.chain )
      throw 'Wrong parameter';
   if( this.observerHash[observer.chain] == null || this.observerHash[observer.chain] == undefined ){
	      throw 'Subject.prototype.RemoveObserver: Property not found in registered observers';
   }
   this.observerHash[observer.chain].RemoveAt(this.observerHash[observer.chain].IndexOf( observer, 0 ));
}

/**
 * A generic way to define a getter/setter for objects in both the legacy
 * Mozilla way and the new ECMA standard way, which should work in I.E. with DOM
 * Elements, but not js objects.
 * 
 * more info on javascript getters and setters: John Resig:
 * http://bit.ly/resig-js-gs-2007 Robert Nyman: http://bit.ly/nyman-js-gs-2009
 * 
 * @author somethingkindawierd@gmail.com (Jon Beebe)
 * @param {string}
 *            label The property name to get/set.
 * @param {function}
 *            getter The get function.
 * @param {function}
 *            setter The set function.
 */
Subject.prototype.addProperty = function(label, getter, setter) {

  if (Object.defineProperty) {
	  try{
		  Object.defineProperty(
			        this,
			        label,
			        {
			          get: getter,
			          set: setter
			        }
			    );
	  }
	  catch(e){
		  // IE8 Bullshit implementation of Object.defineProperty
      }
    
  }
  else if( this.__defineGetter__ ){
    if (getter) {
      this.__defineGetter__(label, getter);
    }
    if (setter) {
      this.__defineSetter__(label, setter);
    }
  }

};

/**
 * A generic way to define a group of getters/setters for objects
 * 
 * @author somethingkindawierd@gmail.com (Jon Beebe)
 * @param {object}
 *            p Set of properties and their getter/setter methods.
 */
Subject.prototype.addProperties = function(p) {
  for (var label in p) {
    if (p.hasOwnProperty(label)) {
      this.addProperty(label, p[label].get, p[label].set);
    }
  }

};

function ChangeWatcher( hostProp, chainInstance, chainPropToWatch ){
	// inherits( new Observer( hostProp ), this );
	this.chain = hostProp;
	this.instance = chainInstance;
	this.chainProp = chainPropToWatch;
	this.Update = function( value )
	{
		if( typeof( this.instance[ this.chainProp ] ) == "function" ){
			this.instance[ this.chainProp ]( value );
		}else{
			this.instance[ this.chainProp ] = value;
		}
	}
};

ChangeWatcher.prototype = new Observer();

function BindingUtils(){
	
}

BindingUtils.bind = function( host, hostProp, chain, chainProp ){
	
	var changeWatcher = new ChangeWatcher( hostProp, chain, chainProp );
	            
	host.AddObserver( changeWatcher );
	
	return changeWatcher;
}